package com.empire.devops.emops.es.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.empire.devops.emops.common.BaseResponse;
import com.empire.devops.emops.es.service.ElasticSearchService;
import com.empire.devops.emops.es.service.EsUtil;
import com.empire.devops.emops.es.vo.EmLogQueryVO;
import com.empire.devops.emops.es.vo.EmLogVO;
import com.empire.devops.emops.es.vo.QueryVO;
import com.empire.devops.emops.utils.ElasticSearchUtil;
import com.empire.devops.emops.utils.PageResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Es数据搜素接口功能
 *
 * @author aaron
 * @date 2021/9/5
 */
@Api(tags = "Es搜素引擎接口API")
@ApiSort(1)
@RestController
@RequestMapping("/elasticSearch")
public class ElasticSearchController {
    private static Logger logger = LoggerFactory.getLogger(ElasticSearchController.class);
    private ElasticSearchService elasticSearchService;
    private EsUtil esUtil;

    @Autowired
    public void setElasticSearchService(ElasticSearchService elasticSearchService) {
        this.elasticSearchService = elasticSearchService;
    }

    @Autowired
    public void setEsUtil(EsUtil esUtil) {
        this.esUtil = esUtil;
    }

    @ApiOperation(value = "ES查询接口", notes = "ES查询接口")
    @ApiOperationSupport(order = 1)
    @RequestMapping(value = "/query", method = {RequestMethod.POST}, consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = {"application/json; charset=UTF-8"})
    public BaseResponse query(@RequestBody QueryVO queryVO) {
        BaseResponse rs = null;
        try {
            Class<?> clazz = ElasticSearchUtil.getClazz(queryVO.getClassName());
            Map<String, Object> params = queryVO.getQuery().get("match");
            Set<String> keys = params.keySet();
            MatchQueryBuilder queryBuilders = null;
            for (String ke : keys) {
                queryBuilders = QueryBuilders.matchQuery(ke, params.get(ke));
            }

            if (null != queryBuilders) {
                SearchSourceBuilder searchSourceBuilder = ElasticSearchUtil.initSearchSourceBuilder(queryBuilders);
                List<?> data = elasticSearchService.search(queryVO.getIdxName(), searchSourceBuilder, clazz);
                rs = BaseResponse.success(data);
            }
        } catch (Exception e) {
            logger.error("query", e);
            rs = BaseResponse.fail();
        }
        return rs;
    }

    @ApiOperation(value = "ES日志分页查询接口", notes = "ES日志分页查询接口")
    @ApiOperationSupport(order = 2)
    @RequestMapping(value = "/logQueryPage", method = {RequestMethod.POST}, consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = {"application/json; charset=UTF-8"})
    public BaseResponse<PageResult<EmLogVO>> logQueryPage(@RequestBody EmLogQueryVO emLogQueryVO) {
        BaseResponse<PageResult<EmLogVO>> rs = null;
        try {
            BoolQueryBuilder queryBuilders = QueryBuilders.boolQuery();
            if (StringUtils.hasLength(emLogQueryVO.getLevel())) {
                queryBuilders.must(QueryBuilders.matchQuery("level", emLogQueryVO.getLevel()));
            }
            if (StringUtils.hasLength(emLogQueryVO.getAppName())) {
                queryBuilders.must(QueryBuilders.matchQuery("appName", emLogQueryVO.getAppName()));
            }
            //关键词模糊查询
            if (StringUtils.hasLength(emLogQueryVO.getMessage())) {
                queryBuilders.must(QueryBuilders.queryStringQuery(emLogQueryVO.getMessage()).field("message"));
//                if (emLogQueryVO.getMessage().contains(Constants.WILDCARD_1) || emLogQueryVO.getMessage().contains(Constants.WILDCARD_2)) {
//                    BoolQueryBuilder boolQueryBuilder = QueryBuilders
//                            .boolQuery()
//                            .should(QueryBuilders.wildcardQuery("message", emLogQueryVO.getMessage()))
//                            .should(QueryBuilders.queryStringQuery(emLogQueryVO.getMessage()).field("message"));
//                    queryBuilders.must(boolQueryBuilder);
////                    queryBuilders.must(QueryBuilders.wildcardQuery("message", emLogQueryVO.getMessage()));
//                } else {
//                    //queryBuilders.must(QueryBuilders.queryStringQuery(emLogQueryVO.getMessage()).field("message"));
//                    queryBuilders.must(QueryBuilders.matchQuery("message", emLogQueryVO.getMessage()));
//                }
            }
            RangeQueryBuilder rangeQuery = null;
            if (emLogQueryVO.getStartTime() != null || emLogQueryVO.getEndTime() != null) {
                rangeQuery = QueryBuilders.rangeQuery("timeMillis");
            }
            if (emLogQueryVO.getStartTime() != null) {
                rangeQuery.gte(emLogQueryVO.getStartTime().getTime());
            }
            if (emLogQueryVO.getEndTime() != null) {
                rangeQuery.lte(emLogQueryVO.getEndTime().getTime());
            }
            if (emLogQueryVO.getStartTime() != null || emLogQueryVO.getEndTime() != null) {
                queryBuilders.must(rangeQuery);
            }
            PageResult<EmLogVO> pageResult = new PageResult<>();
            List<String> idxList = emLogQueryVO.getIdx();
            if (idxList.size() == 0) {
                pageResult.setCount(0);
                pageResult.setList(new ArrayList<>());
                rs = BaseResponse.success(pageResult);
                return rs;
            }
            String[] idxArr = idxList.toArray(new String[idxList.size()]);
            if (null != queryBuilders) {
                SearchSourceBuilder searchSourceBuilder = ElasticSearchUtil.initSearchSourceBuilder(queryBuilders);
                List<Map<String, Object>> data = esUtil.searchListData(idxArr, searchSourceBuilder, emLogQueryVO.getPageSize(), emLogQueryVO.getPage(), null, "timeMillis", "message", SortOrder.DESC);
                List<EmLogVO> emlogVOList = JSON.parseObject(JSON.toJSONString(data), new TypeReference<List<EmLogVO>>() {
                });
                Long count = esUtil.searchCount(idxArr, queryBuilders);
                pageResult.setCount(count.intValue());
                pageResult.setList(emlogVOList);
                rs = BaseResponse.success(pageResult);
            }
        } catch (Exception e) {
            logger.error("logQueryPage", e);
            rs = BaseResponse.fail();
        }
        return rs;
    }
//    @ApiOperation(value = "ES分页查询接口", notes = "ES分页查询接口")
//    @ApiOperationSupport(order = 1)
//    @RequestMapping(value = "/baseLogQueryPage", method = {RequestMethod.POST}, consumes = MediaType.APPLICATION_JSON_VALUE,
//            produces = {"application/json; charset=UTF-8"})
//    public BaseResponse<List<EmlogVO>> baseLogQueryPage(@RequestBody CommonQueryVO commonQueryVO) {
//        BaseResponse<List<EmlogVO>> rs = null;
//        try {
//            Map<String, Object> params = commonQueryVO.getQuery().get("match");
//            Set<String> keys = params.keySet();
//            MatchQueryBuilder queryBuilders = null;
//            for (String ke : keys) {
//                queryBuilders = QueryBuilders.matchQuery(ke, params.get(ke));
//            }
//            if (null != queryBuilders) {
//                SearchSourceBuilder searchSourceBuilder = ElasticSearchUtil.initSearchSourceBuilder(queryBuilders);
//                List<Map<String, Object>> data= esUtil.searchListData(commonQueryVO.getIdxName(),searchSourceBuilder,commonQueryVO.getSize(),commonQueryVO.getFrom(),null,"timeMillis","message", SortOrder.DESC);
//                List<EmlogVO> emlogVOList = JSON.parseObject(JSON.toJSONString(data),new TypeReference<List<EmlogVO>>(){});
//                rs = BaseResponse.success(emlogVOList);
//            }
//        } catch (Exception e) {
//            logger.error("query", e);
//            rs = BaseResponse.fail();
//        }
//        return rs;
//    }

}
